package readconf

import (
	"errors"
	"strconv"
	"fmt"
	"io/ioutil"
	"encoding/json"
	"rwtest/typedef"
)

const (
	filename string = "config.json"
)

func TestRange(value int, low int, high int) int {
	var (
		err error = nil
	)
	if value >= low && value <= high {
		return 0
	} else {
		err = errors.New(strconv.Itoa(value) + " is not between " +
			strconv.Itoa(low) + " and " + strconv.Itoa(high) + ".")
		fmt.Println("Value out of Range:", err.Error())
		return 1
	}
}

func ReadConf() (map[string]string, error) {
	var (
		config map[string]string = make(map[string]string)
		bytes []byte
		err error
	)
	bytes, err = ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println("Read file:", err.Error())
		return nil, err
	}
	err = json.Unmarshal(bytes, &config)
	if err != nil {
		fmt.Println("Unmarshal json:", err.Error())
		return nil, err
	}

	return config, nil
}

func InitConf() (*typedef.CfgStruct, int) {
	const (
		commentText string = "comment"
		lenComment int = len(commentText)
	)
	var (
		// type: pointer, with initialed.
		cfg *typedef.CfgStruct = &typedef.CfgStruct{}
		config map[string]string
		key string
		value string
		ret_code int = 0
		err error
	)
	cfg.Number = make(map[string]int)
	cfg.String = make(map[string]string)
	// Read config.
	if config, err = ReadConf(); err != nil {
		fmt.Println("Read config from json:", err.Error())
		return nil, ret_code
	} else {
		for key, value = range config {
			// skip the key end with "commentText"
			if len(key) >= lenComment &&
				key[len(key) - lenComment:] == commentText {
				continue
			}
			if cfg.Set(key, value) != 0 {
				ret_code = -1
			}
		}
	}

	// Check config
	ret_code = TestRange(cfg.Number["MAX_SIZE"], 0, 32767)
	ret_code = TestRange(cfg.Number["MAX_FILE_COUNT"], 0, 1073676289)
	ret_code = TestRange(cfg.Number["PROCESS_NUMBER"], 1, 1024)
	ret_code = TestRange(cfg.Number["STATUS_REFRESH_TIMEOUT"], 1, 30)
	ret_code = TestRange(cfg.Number["WRITE_WEIGHT"], 1, 1000)
	ret_code = TestRange(cfg.Number["READ_WEIGHT"], 1, 1000)
	ret_code = TestRange(cfg.Number["REMOVE_WEIGHT"], 1, 1000)

	return cfg, ret_code
}

